<template>
  <div tabindex="0" class="ScrollbarLayout_main public_Scrollbar_main" z-index="99"
    :class="{'ScrollbarLayout_mainVertical': !isHorizontal, 'ScrollbarLayout_mainHorizontal': isHorizontal, 'public_Scrollbar_mainOpaque': isOpaque}">
    <div class="ScrollbarLayout_face"
     :class="{'ScrollbarLayout_faceVertical': !isHorizontal, 'ScrollbarLayout_faceHorizontal': isHorizontal}">
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
import Keys from "./vendor/Key";
import cssVar from "./vendor/cssVar";
import DOMMouseMoveTracker from "./vendor/DOMMouseMoveTracker";
import translateDOMPositionXY from "./vendor/translateDOMPositionXY";
import WheelHandler from "./WheelHandler";
import { getWheelEventType } from "./vendor/normalizeWheel";

var UNSCROLLABLE_STATE = {
  position: 0,
  scrollable: false
};

var FACE_MARGIN = parseInt(cssVar("scrollbar-face-margin"), 10);
var FACE_MARGIN_2 = FACE_MARGIN * 2;
var FACE_SIZE_MIN = 30;
var KEYBOARD_SCROLL_AMOUNT = 40;

var _lastScrolledScrollbar = null;
@Component({})
export default class Scrollbar extends Vue {
  static KEYBOARD_SCROLL_AMOUNT = KEYBOARD_SCROLL_AMOUNT;
  static SIZE = parseInt(cssVar("scrollbar-size"), 10);

  @Prop({ default: "vertical", required: true })
  private orientation: string;

  isHorizontal = true;
  isOpaque = false;

  private _wheelHandler;
  private _mouseMoveTracker;
  private _nextState;
  private _stateKey;
  private _stateForKey;
  private _isMounted;

  constructor(a) {
    super();

    // this._onMouseDown = this._onMouseDown.bind(this);
    // this._onMouseMove = this._onMouseMove.bind(this);
    // this._onMouseMoveEnd = this._onMouseMoveEnd.bind(this);
    // this._onFocus = this._onFocus.bind(this);
    // this._onBlur = this._onBlur.bind(this);
    // this._shouldHandleX = this._shouldHandleX.bind(this);
    // this._shouldHandleY = this._shouldHandleY.bind(this);
    // this._shouldHandleChange = this._shouldHandleChange.bind(this);
    // this._onWheel = this._onWheel.bind(this);
    // this._onWheelX = this._onWheelX.bind(this);
    // this._onWheelY = this._onWheelY.bind(this);
    // this._onKeyDown = this._onKeyDown.bind(this);

    // this.state = this._calculateState(
    //   props.position || props.defaultPosition || 0,
    //   props.size,
    //   props.contentSize,
    //   props.orientation
    // );
  }

  created() {
    this.isHorizontal = this.$props.orientation === "horizontal";
  }

  // componentWillReceiveProps(nextProps) {
  //   var controlledPosition = nextProps.position;
  //   if (controlledPosition === undefined) {
  //     this._setNextState(
  //       this._calculateState(
  //         this.state.position,
  //         nextProps.size,
  //         nextProps.contentSize,
  //         nextProps.orientation
  //       )
  //     );
  //   } else {
  //     this._setNextState(
  //       this._calculateState(
  //         controlledPosition,
  //         nextProps.size,
  //         nextProps.contentSize,
  //         nextProps.orientation
  //       ),
  //       nextProps
  //     );
  //   }
  // }

  // render() {
  //   if (!this.state.scrollable) {
  //     return null;
  //   }

  //   var size = this.props.size;
  //   var mainStyle;
  //   var faceStyle;
  //   var isHorizontal = this.state.isHorizontal;
  //   var isVertical = !isHorizontal;
  //   var isActive = this.state.focused || this.state.isDragging;
  //   var faceSize = this.state.faceSize;
  //   var isOpaque = this.props.isOpaque;
  //   var verticalTop = this.props.verticalTop || 0;

  //   var mainClassName = cx({
  //     "ScrollbarLayout/main": true,
  //     "ScrollbarLayout/mainVertical": isVertical,
  //     "ScrollbarLayout/mainHorizontal": isHorizontal,
  //     "public/Scrollbar/main": true,
  //     "public/Scrollbar/mainOpaque": isOpaque,
  //     "public/Scrollbar/mainActive": isActive
  //   });

  //   var faceClassName = cx({
  //     "ScrollbarLayout/face": true,
  //     "ScrollbarLayout/faceHorizontal": isHorizontal,
  //     "ScrollbarLayout/faceVertical": isVertical,
  //     "public/Scrollbar/faceActive": isActive,
  //     "public/Scrollbar/face": true
  //   });

  //   var position = this.state.position * this.state.scale + FACE_MARGIN;

  //   if (isHorizontal) {
  //     mainStyle = {
  //       width: size
  //     };
  //     faceStyle = {
  //       width: faceSize - FACE_MARGIN_2
  //     };
  //     translateDOMPositionXY(faceStyle, position, 0);
  //   } else {
  //     mainStyle = {
  //       top: verticalTop,
  //       height: size
  //     };
  //     faceStyle = {
  //       height: faceSize - FACE_MARGIN_2
  //     };
  //     translateDOMPositionXY(faceStyle, 0, position);
  //   }

  //   mainStyle.zIndex = this.props.zIndex;

  //   if (this.props.trackColor === "gray") {
  //     mainStyle.backgroundColor = cssVar("fbui-desktop-background-light");
  //   }

  //   return (
  //     <div
  //       onFocus={this._onFocus}
  //       onBlur={this._onBlur}
  //       onKeyDown={this._onKeyDown}
  //       onMouseDown={this._onMouseDown}
  //       onWheel={this._wheelHandler.onWheel}
  //       className={mainClassName}
  //       style={mainStyle}
  //       tabIndex={0}
  //     >
  //       <div ref="face" className={faceClassName} style={faceStyle} />
  //     </div>
  //   );
  // }

  // componentWillMount() {
  //   var isHorizontal = this.props.orientation === "horizontal";
  //   var onWheel = isHorizontal ? this._onWheelX : this._onWheelY;

  //   this._wheelHandler = new ReactWheelHandler(
  //     onWheel,
  //     this._shouldHandleX, // Should hanlde horizontal scroll
  //     this._shouldHandleY // Should handle vertical scroll
  //   );
  // }

  // componentDidMount() {
  //   this._isMounted = true;

  //   this._mouseMoveTracker = new DOMMouseMoveTracker(
  //     this._onMouseMove,
  //     this._onMouseMoveEnd,
  //     document.documentElement
  //   );

  //   if (
  //     this.props.position !== undefined &&
  //     this.state.position !== this.props.position
  //   ) {
  //     this._didScroll();
  //   }
  // }

  // componentWillUnmount() {
  //   this._isMounted = false;
  //   this._nextState = null;
  //   this._mouseMoveTracker.releaseMouseMoves();
  //   if (_lastScrolledScrollbar === this) {
  //     _lastScrolledScrollbar = null;
  //   }
  //   delete this._mouseMoveTracker;
  // }

  // scrollBy(delta: number) {
  //   this._onWheel(delta);
  // }

  // _shouldHandleX(delta) {
  //   console.log("shouldHandleX");
  //   return this.props.orientation === "horizontal"
  //     ? this._shouldHandleChange(delta)
  //     : false;
  // }

  // _shouldHandleY(/*number*/ delta) /*boolean*/ {
  //   return this.props.orientation !== "horizontal"
  //     ? this._shouldHandleChange(delta)
  //     : false;
  // }

  // _shouldHandleChange(/*number*/ delta) /*boolean*/ {
  //   var nextState = this._calculateState(
  //     this.state.position + delta,
  //     this.props.size,
  //     this.props.contentSize,
  //     this.props.orientation
  //   );
  //   return nextState.position !== this.state.position;
  // }

  // _calculateState(
  //   position: number,
  //   size,
  //   contentSize: number,
  //   orientation: string
  // ) {
  //   if (size < 1 || contentSize <= size) {
  //     return UNSCROLLABLE_STATE;
  //   }

  //   var stateKey = `${position}_${size}_${contentSize}_${orientation}`;
  //   if (this._stateKey === stateKey) {
  //     return this._stateForKey;
  //   }

  //   // There are two types of positions here.
  //   // 1) Phisical position: changed by mouse / keyboard
  //   // 2) Logical position: changed by props.
  //   // The logical position will be kept as as internal state and the `render()`
  //   // function will translate it into physical position to render.

  //   var isHorizontal = orientation === "horizontal";
  //   var scale = size / contentSize;
  //   var faceSize = size * scale;

  //   if (faceSize < FACE_SIZE_MIN) {
  //     scale = (size - FACE_SIZE_MIN) / (contentSize - size);
  //     faceSize = FACE_SIZE_MIN;
  //   }

  //   var scrollable = true;
  //   var maxPosition = contentSize - size;

  //   if (position < 0) {
  //     position = 0;
  //   } else if (position > maxPosition) {
  //     position = maxPosition;
  //   }

  //   var isDragging = this._mouseMoveTracker
  //     ? this._mouseMoveTracker.isDragging()
  //     : false;

  //   // This function should only return flat values that can be compared quiclky
  //   // by `ReactComponentWithPureRenderMixin`.
  //   var state = {
  //     faceSize,
  //     isDragging,
  //     isHorizontal,
  //     position,
  //     scale,
  //     scrollable
  //   };

  //   // cache the state for later use.
  //   this._stateKey = stateKey;
  //   this._stateForKey = state;
  //   return state;
  // }

  // _onWheelY(deltaX, deltaY) {
  //   this._onWheel(deltaY);
  // }

  // _onWheelX(deltaX, deltaY) {
  //   this._onWheel(deltaX);
  // }

  // _onWheel(delta) {
  //   var props = this.props;

  //   // The mouse may move faster then the animation frame does.
  //   // Use `requestAnimationFrame` to avoid over-updating.
  //   this._setNextState(
  //     this._calculateState(
  //       this.state.position + delta,
  //       props.size,
  //       props.contentSize,
  //       props.orientation
  //     )
  //   );
  // }

  // _onMouseDown(event) {
  //   var nextState;

  //   if (event.target !== ReactDOM.findDOMNode(this.refs.face)) {
  //     // Both `offsetX` and `layerX` are non-standard DOM property but they are
  //     // magically available for browsers somehow.
  //     var nativeEvent = event.nativeEvent;
  //     var position = this.state.isHorizontal
  //       ? nativeEvent.offsetX || nativeEvent.layerX
  //       : nativeEvent.offsetY || nativeEvent.layerY;

  //     // MouseDown on the scroll-track directly, move the center of the
  //     // scroll-face to the mouse position.
  //     var props = this.props;
  //     position /= this.state.scale;
  //     nextState = this._calculateState(
  //       position - this.state.faceSize * 0.5 / this.state.scale,
  //       props.size,
  //       props.contentSize,
  //       props.orientation
  //     );
  //   } else {
  //     nextState = {};
  //   }

  //   nextState.focused = true;
  //   this._setNextState(nextState);

  //   this._mouseMoveTracker.captureMouseMoves(event);
  //   // Focus the node so it may receive keyboard event.
  //   ReactDOM.findDOMNode(this).focus();
  // }

  // _onMouseMove(deltaX, /*number*/ deltaY) {
  //   console.log("_onMouseMove");
  //   var props = this.props;
  //   var delta = this.state.isHorizontal ? deltaX : deltaY;
  //   delta /= this.state.scale;

  //   this._setNextState(
  //     this._calculateState(
  //       this.state.position + delta,
  //       props.size,
  //       props.contentSize,
  //       props.orientation
  //     )
  //   );
  // }

  // _onMouseMoveEnd() {
  //   this._nextState = null;
  //   this._mouseMoveTracker.releaseMouseMoves();
  //   this.setState({ isDragging: false });
  // }

  // _onKeyDown(event) {
  //   var keyCode = event.keyCode;

  //   if (keyCode === Keys.TAB) {
  //     // Let focus move off the scrollbar.
  //     return;
  //   }

  //   var distance = KEYBOARD_SCROLL_AMOUNT;
  //   var direction = 0;

  //   if (this.state.isHorizontal) {
  //     switch (keyCode) {
  //       case Keys.HOME:
  //         direction = -1;
  //         distance = this.props.contentSize;
  //         break;

  //       case Keys.LEFT:
  //         direction = -1;
  //         break;

  //       case Keys.RIGHT:
  //         direction = 1;
  //         break;

  //       default:
  //         return;
  //     }
  //   }

  //   if (!this.state.isHorizontal) {
  //     switch (keyCode) {
  //       case Keys.SPACE:
  //         if (event.shiftKey) {
  //           direction = -1;
  //         } else {
  //           direction = 1;
  //         }
  //         break;

  //       case Keys.HOME:
  //         direction = -1;
  //         distance = this.props.contentSize;
  //         break;

  //       case Keys.UP:
  //         direction = -1;
  //         break;

  //       case Keys.DOWN:
  //         direction = 1;
  //         break;

  //       case Keys.PAGE_UP:
  //         direction = -1;
  //         distance = this.props.size;
  //         break;

  //       case Keys.PAGE_DOWN:
  //         direction = 1;
  //         distance = this.props.size;
  //         break;

  //       default:
  //         return;
  //     }
  //   }

  //   event.preventDefault();

  //   var props = this.props;
  //   this._setNextState(
  //     this._calculateState(
  //       this.state.position + distance * direction,
  //       props.size,
  //       props.contentSize,
  //       props.orientation
  //     )
  //   );
  // }

  // _onFocus() {
  //   this.setState({
  //     focused: true
  //   });
  // }

  // _onBlur() {
  //   this.setState({
  //     focused: false
  //   });
  // }

  // _blur() {
  //   if (this._isMounted) {
  //     try {
  //       this._onBlur();
  //       ReactDOM.findDOMNode(this).blur();
  //     } catch (oops) {
  //       // pass
  //     }
  //   }
  // }

  // _setNextState(nextState, props?) {
  //   props = props || this.props;
  //   var controlledPosition = props.position;
  //   var willScroll = this.state.position !== nextState.position;
  //   if (controlledPosition === undefined) {
  //     var callback = willScroll ? this._didScroll : undefined;
  //     this.setState(nextState, callback);
  //   } else if (controlledPosition === nextState.position) {
  //     this.setState(nextState);
  //   } else {
  //     // Scrolling is controlled. Don't update the state and let the owner
  //     // to update the scrollbar instead.
  //     if (
  //       nextState.position !== undefined &&
  //       nextState.position !== this.state.position
  //     ) {
  //       this.props.onScroll(nextState.position);
  //     }
  //     return;
  //   }

  //   if (willScroll && _lastScrolledScrollbar !== this) {
  //     _lastScrolledScrollbar && _lastScrolledScrollbar._blur();
  //     _lastScrolledScrollbar = this;
  //   }
  // }

  // _didScroll() {
  //   this.props.onScroll(this.state.position);
  // }
}
</script>

<style>
.ScrollbarLayout_main {
  box-sizing: border-box;
  outline: none;
  overflow: hidden;
  position: absolute;
  transition-duration: 250ms;
  transition-timing-function: ease;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

.ScrollbarLayout_mainVertical {
  bottom: 0;
  right: 0;
  top: 0;
  transition-property: background-color width;
  width: 15px;
}

.ScrollbarLayout_mainVertical.public_Scrollbar_mainActive,
.ScrollbarLayout_mainVertical:hover {
  width: 17px;
}

.ScrollbarLayout_mainHorizontal {
  bottom: 0;
  height: 15px;
  left: 0;
  transition-property: background-color height;
}

.ScrollbarLayout_faceVertical {
  left: 0;
  right: 0;
  top: 0;
}

.ScrollbarLayout_face {
  left: 0;
  overflow: hidden;
  position: absolute;
  z-index: 1;
}

.public_Scrollbar_face:after {
  background-color: #c2c2c2;
}

.ScrollbarLayout_faceVertical:after {
  height: 100%;
  left: 4px;
  right: 4px;
  top: 0;
}

.ScrollbarLayout_face:after {
  border-radius: 6px;
  content: "";
  display: block;
  position: absolute;
  transition: background-color 250ms ease;
}

.ScrollbarLayout_faceHorizontal {
  bottom: 0;
  left: 0;
  top: 0;
}

.ScrollbarLayout_faceHorizontal:after {
  bottom: 4px;
  left: 0;
  top: 4px;
  width: 100%;
}

.ScrollbarLayout_faceVertical {
  left: 0;
  right: 0;
  top: 0;
}

.ScrollbarLayout_faceVertical:after {
  height: 100%;
  left: 4px;
  right: 4px;
  top: 0;
}

/* Touching the scroll-track directly makes the scroll-track bolder */
.public_Scrollbar_main.public_Scrollbar_mainActive,
.public_Scrollbar_main:hover {
  background-color: rgba(255, 255, 255, 0.5);
}

.public_Scrollbar_mainOpaque,
.public_Scrollbar_mainOpaque.public_Scrollbar_mainActive,
.public_Scrollbar_mainOpaque:hover {
  background-color: #fff;
}

.public_Scrollbar_face:after {
  background-color: #c2c2c2;
}

.public_Scrollbar_main:hover .public_Scrollbar_face:after,
.public_Scrollbar_mainActive .public_Scrollbar_face:after,
.public_Scrollbar_faceActive:after {
  background-color: #7d7d7d;
}
</style>

